package com.seckill.service.impl;

import com.seckill.common.error.BusinessException;
import com.seckill.common.error.ErrorEnum;
import com.seckill.common.model.ValidationResult;
import com.seckill.common.service.RedisService;
import com.seckill.dao.UserInfoDOMapper;
import com.seckill.dao.UserPasswordDOMapper;
import com.seckill.domain.UserInfoDO;
import com.seckill.domain.UserPasswordDO;
import com.seckill.model.dto.UserDTO;
import com.seckill.service.UserService;
import com.seckill.util.MdUtil;
import com.seckill.util.ValidatorUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 用户
 *
 * @author lill
 * @date 2019-06-05
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserInfoDOMapper userInfoDOMapper;

    @Autowired
    private UserPasswordDOMapper userPasswordDOMapper;

    @Autowired
    private RedisService<String> stringRedisService;

    @Autowired
    private RedisService<UserDTO> userRedisService;

    @Override
    public UserDTO getUserById(Integer id) {
        UserInfoDO userInfoDO = userInfoDOMapper.selectByPrimaryKey(id);
        if (null == userInfoDO) {
            throw new BusinessException(ErrorEnum.USER_NOT_EXIST);
        }
        UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userInfoDO.getId());
        return convertToUserDTO(userInfoDO, userPasswordDO);
    }

    @Override
    public UserDTO getUserByIdInCache(Integer id) {
        UserDTO userDTO = userRedisService.getCache("user_validate_" + id);
        if (null == userDTO) {
            userDTO = getUserById(id);
            userRedisService.setCache("user_validate_" + id, userDTO, 10, TimeUnit.MINUTES);
        }

        return userDTO;
    }

    /**
     * userInfoDO、userPasswordDO 转为 UserDTO
     *
     * @param userInfoDO
     * @param userPasswordDO
     * @return
     */
    private UserDTO convertToUserDTO(UserInfoDO userInfoDO, UserPasswordDO userPasswordDO) {
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(userInfoDO, userDTO);
        userDTO.setTelephone(userInfoDO.getTelphone());
        if (null != userPasswordDO) {
            userDTO.setEncryptPassword(userPasswordDO.getEncrptPassword());
        }
        return userDTO;
    }

    @Override
    public void getOpt(String telephone) {
        if (StringUtils.isBlank(telephone)) {
            throw new BusinessException(ErrorEnum.MISSING_REQUEST_PARAM_ERROR);
        }
        if (!stringRedisService.exists(telephone)) {
            Random random = new Random();
            String opt = String.valueOf(random.nextInt(99999) + 100000);
            stringRedisService.setCache(telephone, opt, 3, TimeUnit.MINUTES);
        }
        // 发送验证码
        System.out.println(telephone + " 验证码：" + stringRedisService.getCache(telephone));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(UserDTO userDTO) {
        if (null == userDTO) {
            throw new BusinessException(ErrorEnum.MISSING_REQUEST_PARAM_ERROR);
        }

        ValidationResult validationResult = ValidatorUtil.validate(userDTO);
        if (validationResult.isHasErrors()) {
            throw new BusinessException(ErrorEnum.VALIDATION_REQUEST_PARAM_ERROR, validationResult.getErrMsg());
        }
        UserInfoDO userInfoDO = new UserInfoDO();
        BeanUtils.copyProperties(userDTO, userInfoDO);
        userInfoDO.setTelphone(userDTO.getTelephone());
        try {
            userInfoDOMapper.insertSelective(userInfoDO);
        } catch (DuplicateKeyException e) {
            throw new BusinessException(ErrorEnum.USER_ALREADY_EXISTS);
        }

        UserPasswordDO userPasswordDO = new UserPasswordDO();
        userPasswordDO.setUserId(userInfoDO.getId());
        userPasswordDO.setEncrptPassword(userDTO.getEncryptPassword());
        userPasswordDOMapper.insertSelective(userPasswordDO);
    }

    @Override
    public UserDTO validateLogin(String telephone, String password) {
        if (StringUtils.isBlank(telephone) ||
                StringUtils.isBlank(password)) {
            throw new BusinessException(ErrorEnum.MISSING_REQUEST_PARAM_ERROR, "手机号或密码不能为空");
        }
        UserInfoDO userInfoDO = userInfoDOMapper.selectByPhone(telephone);
        if (null == userInfoDO) {
            throw new BusinessException(ErrorEnum.USER_PASSWORD_ERROR);
        }
        UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userInfoDO.getId());
        if (!StringUtils.equals(userPasswordDO.getEncrptPassword(), MdUtil.encodeUpperCase32(password))) {
            throw new BusinessException(ErrorEnum.USER_PASSWORD_ERROR);
        }
        return convertToUserDTO(userInfoDO, userPasswordDO);
    }
}
